package com.ssy.lingxi.member.merchant.serviceimpl.paas;

import com.ssy.lingxi.common.constant.basic.EnableDisableStatus;
import com.ssy.lingxi.common.constant.basic.UserLoginSourceEnum;
import com.ssy.lingxi.common.constant.member.MemberLevelTypeEnum;
import com.ssy.lingxi.common.constant.member.MemberTypeEnum;
import com.ssy.lingxi.common.constant.member.RoleTypeEnum;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.common.utils.PasswordUtil;
import com.ssy.lingxi.member.merchant.api.constant.MemberRelationTypeEnum;
import com.ssy.lingxi.member.merchant.config.ServiceConfig;
import com.ssy.lingxi.member.merchant.entity.*;
import com.ssy.lingxi.member.merchant.model.bo.AuthBO;
import com.ssy.lingxi.member.merchant.model.constant.MemberRegisterSourceEnum;
import com.ssy.lingxi.member.merchant.model.constant.MemberStringEnum;
import com.ssy.lingxi.member.merchant.model.constant.MemberUserAuthTypeEnum;
import com.ssy.lingxi.member.merchant.repository.*;
import com.ssy.lingxi.member.merchant.service.paas.IBasePaasService;
import com.ssy.lingxi.member.merchant.utils.AuthBOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * （内部临时服务）系统初始化服务接口实现
 * @author 万宁
 * @version 2.0.0
 * @date 2020-10-15
 */
@Service
public class BasePaasServiceImpl implements IBasePaasService {

    private static final Logger logger = LoggerFactory.getLogger(BasePaasServiceImpl.class);

    @Resource
    private RoleRepository roleRepository;

    @Resource
    private RoleTypeRepository roleTypeRepository;

    @Resource
    private MemberBusinessTypeRepository memberBusinessTypeRepository;

    @Resource
    private MemberTypeRepository memberTypeRepository;

    @Resource
    private MemberRepository memberRepository;

    @Resource
    private MemberUserRepository memberUserRepository;

    @Resource
    private MemberRoleRepository memberRoleRepository;

    @Resource
    private MemberRoleAuthConfigRepository memberRoleAuthConfigRepository;

    @Resource
    private BaseLevelRuleRepository baseLevelRuleRepository;

    @Resource
    private MemberLevelRuleConfigRepository memberLevelRuleConfigRepository;

    @Resource
    private MenuRepository menuRepository;

    @Resource
    private MemberRelationRepository relationRepository;

    @Resource
    private MemberAuthRepository memberAuthRepository;

    @Resource
    private MemberUserAuthRepository memberUserAuthRepository;

    @Resource
    private BaseLevelConfigRepository baseLevelConfigRepository;

    @Resource
    private MemberLevelConfigRepository memberLevelConfigRepository;

    @Resource
    private BaseRightConfigRepository baseRightConfigRepository;

    @Resource
    private MemberRightConfigRepository memberRightConfigRepository;

    @Resource
    private MemberRelationAuthRepository relationAuthRepository;

    /**
     * 创建平台后台会员及用户
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<Void> createManagePlatformAdmin() {
        RoleDO roleDO = roleRepository.findFirstByRelType(MemberRelationTypeEnum.PLATFORM.getCode());
        if(roleDO == null) {
            return Wrapper.success();
        }

        MemberTypeDO memberTypeDO = memberTypeRepository.findByTypeEnum(MemberTypeEnum.MERCHANT.getCode());
        if(memberTypeDO == null) {
            return Wrapper.fail(ResponseCode.BUSINESS_ERROR);
        }

        MemberDO memberDO = memberRepository.findFirstByAccount(ServiceConfig.PLATFORM_SUPER_ADMIN_ACCOUNT);
        if(memberDO == null) {
            memberDO = new MemberDO();
        }
        //设置会员名称
        memberDO.setName(MemberStringEnum.PLATFORM_SUPER_ADMIN_MEMBER_NAME.getName());
        //设置邮箱
        memberDO.setEmail("");
        //设置会员详细信息
        memberDO.setRegisterDetails(new HashSet<>());
        //设置支付密码为空
        memberDO.setPayPassword("");
        //注册时间
        memberDO.setRegisterTime(LocalDateTime.now());
        //注册来源为“管理平台”（与其他会员的区别）
        memberDO.setSource(MemberRegisterSourceEnum.FROM_MANAGE_PLATFORM.getCode());
        //头像logo
        memberDO.setLogo("");

        //密码加密
        //如果更改这里，要同时修改MemberLoginServiceImpl中的用户登录接口的密码校验方式
        String encryptPassword;
        try {
            encryptPassword = PasswordUtil.instance().passwordToMd5String(ServiceConfig.PLATFORM_ADD_MEMBER_DEFAULT_PASSWORD);
        } catch (Exception e) {
            return Wrapper.fail(ResponseCode.BUSINESS_ERROR);
        }

        memberDO.setPassword(encryptPassword);

        //手机号即账号
        memberDO.setCountryCode("");
        memberDO.setPhone("");
        memberDO.setAccount(ServiceConfig.PLATFORM_SUPER_ADMIN_ACCOUNT);


        //设置角色和权限
        Set<RoleDO> roleSet = new HashSet<>();
        roleSet.add(roleDO);
        memberDO.setRoles(roleSet);

        //会员权限：CascadeType = PERSIST，所以会关联保存
        MemberAuthDO memberAuthDO = new MemberAuthDO();
        memberAuthDO.setAuth(roleDO.getRoleAuth().getAuth());
        memberAuthDO.setMember(memberDO);

        memberDO.setMemberAuth(memberAuthDO);
        //平台会员和角色不需要等级信息、信用信息
        memberRepository.saveAndFlush(memberDO);

        //Step 2: 首先创建“超级管理员”角色 与 超级管理员用户
        MemberRoleDO memberRoleDO;
        if(CollectionUtils.isEmpty(memberDO.getMemberRoles())) {
            memberRoleDO = new MemberRoleDO();
        } else {
            memberRoleDO = memberDO.getMemberRoles().stream().filter(r -> r.getTypeEnum().equals(MemberUserAuthTypeEnum.ADMIN.getCode())).findFirst().orElse(null);
            if(memberRoleDO == null) {
                memberRoleDO = new MemberRoleDO();
            }
        }

        memberRoleDO.setRoleName(MemberStringEnum.PLATFORM_SUPER_ADMIN_MEMBER_ROLE_NAME.getName());
        memberRoleDO.setTypeEnum(MemberUserAuthTypeEnum.ADMIN.getCode());
        //平台后台不具有IM权限和数据权限
        memberRoleDO.setHasImAuth(EnableDisableStatus.DISABLE.getCode());
        memberRoleDO.setAuthConfig(new HashSet<>());

        //权限设置
        memberRoleDO.setRemark(MemberStringEnum.MEMBER_ADMIN_ROLE_DEFAULT_REMARK.getName());
        memberRoleDO.setStatus(EnableDisableStatus.ENABLE.getCode());
        memberRoleDO.setMember(memberDO);
        memberRoleDO = memberRoleRepository.save(memberRoleDO);

        if(CollectionUtils.isEmpty(memberDO.getMemberRoles())) {
            Set<MemberRoleDO> memberRoleDoSet = new HashSet<>();
            memberRoleDoSet.add(memberRoleDO);
            memberDO.setMemberRoles(memberRoleDoSet);
        } else {
            if(memberDO.getMemberRoles().stream().noneMatch(r -> r.getTypeEnum().equals(MemberUserAuthTypeEnum.ADMIN.getCode()))) {
                memberDO.getMemberRoles().add(memberRoleDO);
            }
        }

        //Step 2: 创建 超级管理员用户
        MemberUserDO userDO;
        if(CollectionUtils.isEmpty(memberDO.getUsers())) {
            userDO = new MemberUserDO();
            userDO.setCreateTime(LocalDateTime.now());
        } else {
            userDO = memberDO.getUsers().stream().filter(u -> u.getAccount().equals(ServiceConfig.PLATFORM_SUPER_ADMIN_ACCOUNT)).findFirst().orElse(null);
            if(userDO == null) {
                userDO = new MemberUserDO();
                userDO.setCreateTime(LocalDateTime.now());
            }
        }

        userDO.setAccount(memberDO.getAccount());
        userDO.setPhone(memberDO.getPhone());
        userDO.setPassword(memberDO.getPassword());
        userDO.setCountryCode(memberDO.getCountryCode());
        userDO.setName(memberDO.getName());
        userDO.setEmail(memberDO.getEmail());
        userDO.setIdCardNo("");
        userDO.setLogo("");
        userDO.setJobTitle(MemberStringEnum.PLATFORM_SUPER_ADMIN_JOB_TITLE.getName());
        userDO.setStatus(EnableDisableStatus.ENABLE.getCode());
        userDO.setRelType(MemberRelationTypeEnum.PLATFORM.getCode());
        userDO.setTypeEnum(MemberUserAuthTypeEnum.ADMIN.getCode());
        userDO.setIsSales(EnableDisableStatus.DISABLE.getCode());
        userDO.setMember(memberDO);
        if(CollectionUtils.isEmpty(userDO.getRoles())) {
            Set<MemberRoleDO> memberRoleSet = new HashSet<>();
            memberRoleSet.add(memberRoleDO);
            userDO.setRoles(memberRoleSet);
        } else {
            if(userDO.getRoles().stream().noneMatch(r -> r.getTypeEnum().equals(MemberUserAuthTypeEnum.ADMIN.getCode()))) {
                userDO.getRoles().add(memberRoleDO);
            }
        }

        //权限
        MemberUserAuthDO userAuthDO = new MemberUserAuthDO();
        userAuthDO.setAuth(memberDO.getMemberAuth().getAuth());
        userAuthDO.setDataAuth(new ArrayList<>());
        userAuthDO.setChannelAuth(new ArrayList<>());
        userAuthDO.setChannels(new HashSet<>());
        userAuthDO.setUser(userDO);
        userDO.setUserAuth(userAuthDO);
        memberUserRepository.save(userDO);

        if(CollectionUtils.isEmpty(memberDO.getUsers())) {
            Set<MemberUserDO> memberUserSet = new HashSet<>();
            memberUserSet.add(userDO);
            memberDO.setUsers(memberUserSet);
        } else {
            if(memberDO.getUsers().stream().noneMatch(u -> u.getAccount().equals(ServiceConfig.PLATFORM_SUPER_ADMIN_ACCOUNT))) {
                memberDO.getUsers().add(userDO);
            }
        }

        memberRepository.saveAndFlush(memberDO);

        //创建平台会员的升级规则
        List<BaseLevelRuleDO> baseLevelRuleDOList = baseLevelRuleRepository.findAll().stream().filter(rule -> rule.getMemberLevelTypeEnum().equals(MemberLevelTypeEnum.PLATFORM.getCode()) && rule.getStatus().equals(EnableDisableStatus.ENABLE.getCode())).collect(Collectors.toList());
        if(!CollectionUtils.isEmpty(baseLevelRuleDOList)) {
            List<MemberLevelRuleConfigDO> memberLevelRuleConfigDOList = memberLevelRuleConfigRepository.findByMemberIdAndRoleId(memberDO.getId(), roleDO.getId());
            for (BaseLevelRuleDO baseLevelRuleDO : baseLevelRuleDOList) {
                MemberLevelRuleConfigDO memberLevelRuleConfigDO = memberLevelRuleConfigDOList.stream().filter(config -> config.getRule().getId().equals(baseLevelRuleDO.getId())).findFirst().orElse(null);
                if(memberLevelRuleConfigDO == null) {
                    memberLevelRuleConfigDO = new MemberLevelRuleConfigDO();
                    memberLevelRuleConfigDO.setMemberId(memberDO.getId());
                    memberLevelRuleConfigDO.setRoleId(roleDO.getId());
                    memberLevelRuleConfigDO.setRule(baseLevelRuleDO);
                    memberLevelRuleConfigDO.setScore(new BigDecimal(0));
                    memberLevelRuleConfigDO.setStatus(EnableDisableStatus.ENABLE.getCode());
                    memberLevelRuleConfigRepository.saveAndFlush(memberLevelRuleConfigDO);
                }
            }
        }

        return Wrapper.success();
    }

    /**
     * 系统初始化时，创建“平台”角色、平台后台管理员账号
     */
    @Override
    public void initPlatformAdmin() {
        MemberTypeDO memberTypeDO = memberTypeRepository.findByTypeEnum(MemberTypeEnum.MERCHANT.getCode());
        if(memberTypeDO == null) {
            return;
        }

        RoleTypeDO roleTypeDO = roleTypeRepository.findFirstByTypeEnum(RoleTypeEnum.SERVICE_PROVIDER.getCode());
        if(roleTypeDO == null) {
            return;
        }

        //密码加密
        String encryptPassword;
        try {
            encryptPassword = PasswordUtil.instance().passwordToMd5String(ServiceConfig.PLATFORM_ADD_MEMBER_DEFAULT_PASSWORD);
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }

        MemberBusinessTypeDO businessTypeDO = memberBusinessTypeRepository.findFirstByRelType(MemberRelationTypeEnum.PLATFORM.getCode());
        if(businessTypeDO == null) {
            businessTypeDO = new MemberBusinessTypeDO();
        }

        businessTypeDO.setRelType(MemberRelationTypeEnum.PLATFORM.getCode());
        businessTypeDO.setBusinessTypeName(MemberStringEnum.PLATFORM_ROLE_BUSINESS_NAME.getName());
        memberBusinessTypeRepository.saveAndFlush(businessTypeDO);

        RoleDO roleDO = new RoleDO();
        roleDO.setRoleName(MemberStringEnum.PLATFORM_ROLE_NAME.getName());
        roleDO.setRelType(MemberRelationTypeEnum.PLATFORM.getCode());
        roleDO.setStatus(EnableDisableStatus.ENABLE.getCode());
        roleDO.setMemberType(memberTypeDO);
        roleDO.setRoleType(roleTypeDO);
        roleDO.setBusinessType(businessTypeDO);
        roleDO.setRoleType(roleTypeDO);
        roleDO.setMemberType(memberTypeDO);

        RoleAuthDO authDO = new RoleAuthDO();
        authDO.setRole(roleDO);

        List<MenuDO> menuList = menuRepository.findBySource(UserLoginSourceEnum.BUSINESS_MANAGEMENT_PLATFORM.getCode());
        if(CollectionUtils.isEmpty(menuList)) {
            authDO.setAuth(new ArrayList<>());
        } else {
            List<AuthBO> authList = menuList.stream().map(menu -> new AuthBO(menu.getId(), menu.getParentId(), StringUtils.hasLength(menu.getCode()) ? menu.getCode() : "", menu.getUrl(), menu.getTitle(), menu.getOrder(), menu.getSource(), menu.getAttrs(), new ArrayList<>(), menu.getDisabled() ? EnableDisableStatus.DISABLE.getCode() : EnableDisableStatus.ENABLE.getCode())).collect(Collectors.toList());
            authDO.setAuth(authList);
        }

        roleDO.setRoleAuth(authDO);
        roleDO.setMembers(new HashSet<>());
        roleDO.setConfigs(new HashSet<>());
        roleRepository.saveAndFlush(roleDO);

        MemberDO memberDO = new MemberDO();
        memberDO.setName(MemberStringEnum.PLATFORM_SUPER_ADMIN_MEMBER_NAME.getName());
        memberDO.setEmail("");
        memberDO.setRegisterDetails(new HashSet<>());
        memberDO.setPayPassword("");
        memberDO.setRegisterTime(LocalDateTime.now());
        //注册来源为“管理平台”（与其他会员的区别）
        memberDO.setSource(MemberRegisterSourceEnum.FROM_MANAGE_PLATFORM.getCode());
        memberDO.setLogo("");
        memberDO.setPassword(encryptPassword);
        memberDO.setCountryCode("");
        memberDO.setPhone("");
        memberDO.setAccount(ServiceConfig.PLATFORM_SUPER_ADMIN_ACCOUNT);

        //设置角色和权限
        Set<RoleDO> roleSet = new HashSet<>();
        roleSet.add(roleDO);
        memberDO.setRoles(roleSet);

        MemberAuthDO memberAuthDO = new MemberAuthDO();
        memberAuthDO.setAuth(roleDO.getRoleAuth().getAuth());
        memberAuthDO.setMember(memberDO);

        memberDO.setMemberAuth(memberAuthDO);
        //平台会员和角色不需要等级信息、信用信息
        memberRepository.saveAndFlush(memberDO);

        //Step 2: 首先创建“超级管理员”角色 与 超级管理员用户
        MemberRoleDO memberRoleDO = new MemberRoleDO();
        memberRoleDO.setRoleName(MemberStringEnum.PLATFORM_SUPER_ADMIN_MEMBER_ROLE_NAME.getName());
        memberRoleDO.setTypeEnum(MemberUserAuthTypeEnum.ADMIN.getCode());
        memberRoleDO.setAuth(roleDO.getRoleAuth().getAuth());
        //平台后台不具有IM权限和数据权限
        memberRoleDO.setHasImAuth(EnableDisableStatus.DISABLE.getCode());
        memberRoleDO.setAuthConfig(new HashSet<>());
        memberRoleDO.setRemark(MemberStringEnum.MEMBER_ADMIN_ROLE_DEFAULT_REMARK.getName());
        memberRoleDO.setStatus(EnableDisableStatus.ENABLE.getCode());
        memberRoleDO.setMember(memberDO);
        memberRoleRepository.save(memberRoleDO);

        memberDO.setMemberRoles(new HashSet<>(Stream.of(memberRoleDO).collect(Collectors.toList())));

        //Step 2: 创建 超级管理员用户
        MemberUserDO userDO = new MemberUserDO();
        userDO.setCreateTime(LocalDateTime.now());
        userDO.setAccount(memberDO.getAccount());
        userDO.setPhone(memberDO.getPhone());
        userDO.setPassword(memberDO.getPassword());
        userDO.setCountryCode(memberDO.getCountryCode());
        userDO.setName(memberDO.getName());
        userDO.setEmail(memberDO.getEmail());
        userDO.setIdCardNo("");
        userDO.setLogo("");
        userDO.setJobTitle(MemberStringEnum.PLATFORM_SUPER_ADMIN_JOB_TITLE.getName());
        userDO.setStatus(EnableDisableStatus.ENABLE.getCode());
        userDO.setRelType(MemberRelationTypeEnum.PLATFORM.getCode());
        userDO.setTypeEnum(MemberUserAuthTypeEnum.ADMIN.getCode());
        userDO.setIsSales(EnableDisableStatus.DISABLE.getCode());
        userDO.setMember(memberDO);
        userDO.setRoles(new HashSet<>(Stream.of(memberRoleDO).collect(Collectors.toList())));

        //权限
        MemberUserAuthDO userAuthDO = new MemberUserAuthDO();
        userAuthDO.setAuth(memberDO.getMemberAuth().getAuth());
        userAuthDO.setDataAuth(new ArrayList<>());
        userAuthDO.setChannelAuth(new ArrayList<>());
        userAuthDO.setChannels(new HashSet<>());
        userAuthDO.setUser(userDO);
        userDO.setUserAuth(userAuthDO);
        memberUserRepository.save(userDO);

        memberDO.setUsers(new HashSet<>(Stream.of(userDO).collect(Collectors.toList())));
        memberRepository.saveAndFlush(memberDO);

        //创建平台会员的升级规则
        List<BaseLevelRuleDO> baseLevelRuleDOList = baseLevelRuleRepository.findByMemberLevelTypeEnumAndStatus(MemberLevelTypeEnum.PLATFORM.getCode(), EnableDisableStatus.ENABLE.getCode());
        List<MemberLevelRuleConfigDO> memberLevelRuleConfigList = baseLevelRuleDOList.stream().map(baseLevelRuleDO -> {
            MemberLevelRuleConfigDO configDO = new MemberLevelRuleConfigDO();
            configDO.setMemberId(memberDO.getId());
            configDO.setRoleId(roleDO.getId());
            configDO.setRule(baseLevelRuleDO);
            configDO.setScore(new BigDecimal(0));
            configDO.setStatus(EnableDisableStatus.ENABLE.getCode());
            return configDO;
        }).collect(Collectors.toList());
        memberLevelRuleConfigRepository.saveAll(memberLevelRuleConfigList);
    }

    /**
     * 重新构建菜单的level和key字段
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public void rebuildMenuLevelAndKey() {
        List<MenuDO> menuList = menuRepository.findAll();

        if(CollectionUtils.isEmpty(menuList)) {
            Wrapper.success();
            return;
        }

        List<MenuDO> topMenus = menuList.stream().filter(menuDO -> menuDO.getParentId().equals(0L)).collect(Collectors.toList());
        for (MenuDO topMenu : topMenus) {
            topMenu.setLevel(1);
            topMenu.setKey(String.valueOf(topMenu.getOrder()));
            recurseBuildSubMenuLevelAndKey(topMenu, menuList);
        }

        menuRepository.saveAll(menuList);
        Wrapper.success();
    }

    /**
     * 重新构建会员及其超级管理员权限
     *
     * @param memberDO 会员
     */
    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public Wrapper<Void> rebuildMemberAuth(MemberDO memberDO) {
        //Step 1: 更新会员的权限
        List<RoleDO> roleDOList = new ArrayList<>(memberDO.getRoles());
        List<AuthBO> mergeAuthList = AuthBOUtils.mergeAndDistinct(roleDOList.stream().map(role -> role.getRoleAuth().getAuth()).collect(Collectors.toList()));
        MemberAuthDO memberAuthDO = memberDO.getMemberAuth();
        memberAuthDO.setAuth(mergeAuthList);
        memberAuthRepository.saveAndFlush(memberAuthDO);

        //Step 2: 更新超管用户的权限
        MemberUserDO memberUserDO = memberUserRepository.findFirstByMemberAndTypeEnum(memberDO, MemberUserAuthTypeEnum.ADMIN.getCode());
        if(memberUserDO == null) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_USER_DOES_NOT_EXIST);
        }

        MemberUserAuthDO userAuthDO = memberUserDO.getUserAuth();
        userAuthDO.setAuth(memberUserDO.getMember().getMemberAuth().getAuth());
        memberUserAuthRepository.saveAndFlush(userAuthDO);

        return Wrapper.success();
    }

    /**
     * 递归构建子菜单的Level和Key字段
     * @param upperMenu 上级菜单
     * @param menuList 菜单列表
     */
    private void recurseBuildSubMenuLevelAndKey(MenuDO upperMenu, List<MenuDO> menuList) {
        List<MenuDO> subMenus = menuList.stream().filter(menuDO -> menuDO.getParentId().equals(upperMenu.getId()) && menuDO.getSource().equals(upperMenu.getSource())).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(subMenus)) {
            return;
        }

        for (MenuDO subMenu : subMenus) {
            subMenu.setLevel(upperMenu.getLevel() + 1);
            subMenu.setKey(upperMenu.getKey() + "-" + subMenu.getOrder());
            recurseBuildSubMenuLevelAndKey(subMenu, menuList);
        }
    }

    /**
     * 根据角色权限，重新构建所有权限
     *
     * @param roleDO 会员角色
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Wrapper<Void> rebuildAuth(RoleDO roleDO) {
        //Step 1: 更新会员的权限
        List<MemberDO> memberDOList = new ArrayList<>(roleDO.getMembers());
        List<MemberAuthDO> memberAuthDOList = new ArrayList<>();
        for (MemberDO memberDO : memberDOList) {
            List<RoleDO> roleDOList = new ArrayList<>(memberDO.getRoles());

            List<AuthBO> mergeAuthList = AuthBOUtils.mergeAndDistinct(roleDOList.stream().map(role -> AuthBOUtils.copyList(role.getRoleAuth().getAuth())).collect(Collectors.toList()));
            MemberAuthDO memberAuthDO = memberDO.getMemberAuth();
            memberAuthDO.setAuth(mergeAuthList);
            memberAuthDOList.add(memberAuthDO);
        }

        memberAuthRepository.saveAll(memberAuthDOList);

        //Step 2: 更新会员角色的权限
        List<MemberRoleDO> memberRoleDOList = memberDOList.stream().flatMap(memberDO -> memberDO.getMemberRoles().stream()).collect(Collectors.toList());
        for (MemberRoleDO memberRoleDO : memberRoleDOList) {
            MemberDO memberDO = memberRoleDO.getMember();
            if(memberRoleDO.getTypeEnum().equals(MemberUserAuthTypeEnum.ADMIN.getCode())) {
                memberRoleDO.setAuth(memberDO.getMemberAuth().getAuth());
            } else {
                AuthBOUtils.removeInSource(memberRoleDO.getAuth(), memberDO.getMemberAuth().getAuth());
            }
        }
        memberRoleRepository.saveAll(memberRoleDOList);

        //Step 3: 更新用户的权限
        List<MemberUserDO> userDOList = memberDOList.stream().flatMap(memberDO -> memberDO.getUsers().stream()).collect(Collectors.toList());
        List<MemberUserAuthDO> memberUserAuthDOList = new ArrayList<>();
        for (MemberUserDO memberUserDO : userDOList) {
            MemberUserAuthDO userAuthDO = memberUserDO.getUserAuth();
            if(memberUserDO.getTypeEnum().equals(MemberUserAuthTypeEnum.ADMIN.getCode())) {
                userAuthDO.setAuth(memberUserDO.getMember().getMemberAuth().getAuth());
            } else {
                List<AuthBO> mergeAuthList = AuthBOUtils.mergeAndDistinct(memberUserDO.getRoles().stream().map(memberRoleDO -> AuthBOUtils.copyList(memberRoleDO.getAuth())).collect(Collectors.toList()));
                userAuthDO.setAuth(mergeAuthList);
            }
            memberUserAuthDOList.add(userAuthDO);
        }
        memberUserAuthRepository.saveAll(memberUserAuthDOList);

        //Step 4: 更新平台会员的权限
        Specification<MemberRelationDO> specification = (Specification<MemberRelationDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("relType").as(Integer.class), MemberRelationTypeEnum.PLATFORM.getCode()));
            list.add(criteriaBuilder.equal(root.get("subRole").as(RoleDO.class), roleDO));
            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };
        List<MemberRelationDO> relationDOList = relationRepository.findAll(specification);

        List<MemberRelationAuthDO> relationAuthDOList = new ArrayList<>();
        for (MemberRelationDO relationDO : relationDOList) {
            MemberRelationAuthDO relationAuthDO = relationDO.getRelationAuth();
            relationAuthDO.setAuth(AuthBOUtils.copyList(roleDO.getRoleAuth().getAuth()));
            relationAuthDOList.add(relationAuthDO);
        }

        if(!CollectionUtils.isEmpty(relationAuthDOList)) {
            relationAuthRepository.saveAll(relationAuthDOList);
        }

        return Wrapper.success();
    }

    /**
     * 禁用菜单可配置数据权限时，删除已有的数据权限配置
     * @param menuId 菜单Id
     * @param url 菜单Url
     * @param source 菜单Source
     */
    @Async
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public void removeDataAuthAsync(Long menuId, String url, Integer source) {
        try {
            Specification<MemberRoleAuthConfigDO> specification = (Specification<MemberRoleAuthConfigDO>) (root, query, criteriaBuilder) -> {
                List<Predicate> list = new ArrayList<>();

                Join<Object, Object> menuJoin = root.join("menu", JoinType.LEFT);
                list.add(criteriaBuilder.equal(menuJoin.get("id").as(Long.class), menuId));
                Predicate[] p = new Predicate[list.size()];
                return criteriaBuilder.and(list.toArray(p));
            };

            List<MemberRoleAuthConfigDO> authConfigs = memberRoleAuthConfigRepository.findAll(specification);

            if(CollectionUtils.isEmpty(authConfigs)) {
                return;
            }

            //删除所有用户数据权限中的此菜单
            Specification<MemberUserDO> specUser = (Specification<MemberUserDO>) (root, query, criteriaBuilder) -> {
                List<Predicate> list = new ArrayList<>();

                Join<MemberUserDO, MemberRoleDO> roleJoin = root.join("roles", JoinType.LEFT);
                Join<MemberRoleDO, MemberRoleAuthConfigDO> authJoin = roleJoin.join("authConfig", JoinType.LEFT);
                Join<MemberRoleAuthConfigDO, MenuDO> menuJoin = authJoin.join("menu", JoinType.LEFT);
                list.add(criteriaBuilder.equal(menuJoin.get("id").as(Long.class), menuId));
                Predicate[] p = new Predicate[list.size()];
                return criteriaBuilder.and(list.toArray(p));
            };

            List<MemberUserDO> memberUserDOList = memberUserRepository.findAll(specUser);
            if(!CollectionUtils.isEmpty(memberUserDOList)) {
                List<MemberUserAuthDO> memberUserAuthList = memberUserAuthRepository.findByUserIn(memberUserDOList);
                memberUserAuthList.forEach(memberUserAuth -> memberUserAuth.getDataAuth().removeIf(dataAuthBO -> dataAuthBO.getUrl().equals(url) && dataAuthBO.getSource().equals(source)));

                memberUserAuthRepository.saveAll(memberUserAuthList);
            }

            //删除此菜单
            for (MemberRoleAuthConfigDO authConfig : authConfigs) {
                authConfig.getOrgs().clear();
                memberRoleAuthConfigRepository.saveAndFlush(authConfig);
            }

            memberRoleAuthConfigRepository.deleteAll(authConfigs);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            logger.error("Paas修改数据权限错误", e);
        }
    }
}
